package com.cjq.green.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.green20220302.Client;
import com.aliyun.green20220302.models.TextModerationRequest;
import com.aliyun.green20220302.models.TextModerationResponse;
import com.aliyun.green20220302.models.TextModerationResponseBody;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.cjq.green.config.GreenConf;
import com.cjq.green.config.GreenProperties;
import com.cjq.green.constant.DetectionTextType;
import com.cjq.green.constant.EndPointConstant;
import com.cjq.green.service.GreenTextService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Import(GreenConf.class)
@Slf4j
public class GreenText implements GreenTextService {

    @Resource
    private Client client;
    @Resource
    private Config config;
    @Resource
    private GreenProperties greenProperties;



    /**
     * 执行文本内容安全检测服务
     *
     * @param content 待检测的文本内容，不能为空
     * @param type    文本检测类型枚举，指定检测服务类型
     * @return 检测结果的Map，包含以下键值对：
     *              <dl>
     *                  <dt>-labels: 检测到的风险标签集合<br></dt>
     *                  <dt>-reason: 检测结果的原因描述</dt>
     *                  <dd>-riskLevel: 风险等级（high-高风险（拒绝处理），medium-中风险（人工复查处理），low低风险（高召回需求时处理））</dd>
     *                  <dd>-riskTips: 细分标签，作拒绝理由</dd>
     *              </dl>
     *         例如：{reason={"riskLevel":"medium","riskTips":"辱骂_低俗"}, labels=profanity}<br>
     *         发生异常或检测失败时返回null; 检测通过返回空Map
     */
    @Override
    public Map<String, String> scan(String content, DetectionTextType type) {
        /**
         * 输入参数校验模块
         * 验证文本内容有效性，空内容触发非法参数异常
         * 包含空值和空字符串双重校验
         */
        if (content == null || content.isEmpty()){
            log.error("空参:{}","com.cjq.green.service.impl.GreenText");
            throw new IllegalArgumentException("待检测的文本内容，不能为空");
        }

        /**
         * HTTP超时配置模块
         * 设置同步请求的连接和读取超时参数
         * 统一设置为10秒超时阈值
         */
        RuntimeOptions runtimeOptions = new RuntimeOptions();
        runtimeOptions.readTimeout = 10000;
        runtimeOptions.connectTimeout = 10000;

        /**
         * 请求参数构建模块
         * 创建包含文本内容的服务参数JSON对象
         * 构建文本审核请求对象并指定服务类型
         */
        JSONObject serviceParameters = new JSONObject();
        serviceParameters.put("content",content);

        TextModerationRequest textModerationRequest = new TextModerationRequest();
        textModerationRequest.setService(type.getServiceName());
        textModerationRequest.setServiceParameters(serviceParameters.toJSONString());

        try {
            /**
             * 同步文本审核请求模块
             * 发起首次文本内容安全检测请求
             * 包含服务端错误自动重试机制
             */
            TextModerationResponse response = client.textModerationWithOptions(textModerationRequest, runtimeOptions);

            /**
             * 服务端错误处理模块
             * 检测到500错误时执行区域切换重试机制
             * 自动切换到备用区域节点进行重试
             */
            if (response != null) {
                if (500 == response.getStatusCode() ||
                   (response.getBody() != null && 500 == (response.getBody().getCode()))) {
                    config.setRegionId(EndPointConstant.getEndPoint(greenProperties.getSpareRegionId()).getRegion());
                    config.setEndpoint(EndPointConstant.getEndPoint(greenProperties.getSpareRegionId()).getEndPoint());
                    Client temporaryClient = new Client(config);
                    response = temporaryClient.textModerationWithOptions(textModerationRequest, runtimeOptions);
                }
            }

            /**
             * 响应结果处理模块
             * 处理服务端返回结果并构建输出数据结构
             * 包含成功响应处理和错误日志记录
             */
            if (response != null) {
                if (response.getStatusCode() == 200) {
                    TextModerationResponseBody result = response.getBody();
                    Integer code = result.getCode();
                    if (code != null && code == 200) {
                        log.info("文本审核结果:{}", JSON.toJSONString(result));
                        HashMap<String, String> map = new HashMap<>();
                        TextModerationResponseBody.TextModerationResponseBodyData data = result.getData();
                        String reason = data.getReason();
                        String labels = data.getLabels();
                        if ((reason == null || reason.isEmpty()) && (labels==null || labels.isEmpty())){
                            return Collections.emptyMap();
                        }
                        JSONObject object = JSON.parseObject(reason);
                        JSONObject reasonObject = new JSONObject();
                        reasonObject.put("riskLevel", object.getString("riskLevel"));
                        reasonObject.put("riskTips", object.getString("riskTips"));
                        reason  = JSON.toJSONString(reasonObject);
                        map.put("labels",labels);
                        map.put("reason",reason);
                        return map;
                    } else {
                        System.out.println("text moderation not success. code:" + code);
                    }
                } else {
                    System.out.println("response not success. status:" + response.getStatusCode());
                }
            }
        }catch (Exception e) {
            /**
             * 全局异常捕获模块
             * 记录运行时异常并返回空结果
             * 包含所有未处理的异常类型
             */
            log.error("发生异常:",e);
        }
        return null;
    }

    /**
     * 默认的执行文本内容安全检测服务
     *
     * @param content 待检测的文本内容，不能为空
     * @return 检测结果的Map，包含以下键值对：
     *              <dl>
     *                  <dt>-labels: 检测到的风险标签集合<br></dt>
     *                  <dt>-reason: 检测结果的原因描述</dt>
     *                  <dd>-riskLevel: 风险等级（high-高风险（拒绝处理），medium-中风险（人工复查处理），low低风险（高召回需求时处理））</dd>
     *                  <dd>-riskTips: 细分标签，作拒绝理由</dd>
     *              </dl>
     *         例如：{reason={"riskLevel":"medium","riskTips":"辱骂_低俗"}, labels=profanity}<br>
     *         发生异常或检测失败时返回null; 检测通过返回空Map
     */
    @Override
    public Map<String, String> scan(String content) {
        return scan(content,DetectionTextType.DEFAULT);
    }


}
